home *** CD-ROM | disk | FTP | other *** search
- /*
-
- File: ext2_dir.c
-
- Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
-
- This software is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
- #ifdef HAVE_E2FSPROGS
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <time.h>
- #include <sys/stat.h>
- #include "ext2fs/ext2_fs.h"
- #include "ext2fs/ext2fs.h"
- #include "types.h"
- #include "common.h"
- #include "intrface.h"
- #include "dir.h"
- #include "ext2_dir.h"
-
- #define DIRENT_DELETED_FILE 4
- /*
- * list directory
- */
-
- #define LONG_OPT 0x0001
-
- struct list_dir_struct {
- t_file_data *dir_list;
- t_file_data *current_file;
- ext2_filsys current_fs;
- int flags;
- };
-
-
- /*
- * I/O Manager routine prototypes
- */
- static errcode_t my_open(const char *dev, int flags, io_channel *channel);
- static errcode_t my_close(io_channel channel);
- static errcode_t my_set_blksize(io_channel channel, int blksize);
- static errcode_t my_read_blk(io_channel channel, unsigned long block, int count, void *buf);
- static errcode_t my_write_blk(io_channel channel, unsigned long block, int count, const void *buf);
- static errcode_t my_flush(io_channel channel);
-
-
- static io_channel alloc_io_channel(t_param_disk *disk_car,t_diskext *partition);
-
- static struct struct_io_manager my_struct_manager = {
- magic: EXT2_ET_MAGIC_IO_MANAGER,
- name: "TestDisk I/O Manager",
- open: my_open,
- close: my_close,
- set_blksize: my_set_blksize,
- read_blk: my_read_blk,
- write_blk: my_write_blk,
- flush: my_flush,
- write_byte: NULL
- };
-
- io_manager my_io_manager = &my_struct_manager;
- /*
- * Macro taken from unix_io.c
- * For checking structure magic numbers...
- */
-
- #define EXT2_CHECK_MAGIC(struct, code) \
- if ((struct)->magic != (code)) return (code)
-
- /*
- * Allocate libext2fs structures associated with I/O manager
- */
- static io_channel alloc_io_channel(t_param_disk *disk_car,t_diskext *partition)
- {
- io_channel ioch;
- t_my_data *my_data;
- #ifdef DEBUG
- ecrit_rapport("alloc_io_channel start\n");
- #endif
- ioch = (io_channel)malloc(sizeof(struct struct_io_channel));
- if (ioch==NULL)
- return NULL;
- memset(ioch, 0, sizeof(struct struct_io_channel));
- ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL;
- ioch->manager = my_io_manager;
- ioch->name = (char *)malloc(strlen(partition->name)+1);
- if (ioch->name==NULL) {
- free(ioch);
- return NULL;
- }
- strncpy(ioch->name, partition->name,sizeof(ioch->name));
- my_data=MALLOC(sizeof(*my_data));
- my_data->partition=partition;
- my_data->disk_car=disk_car;
- ioch->private_data = my_data;
- ioch->block_size = 1024; /* The smallest ext2fs block size */
- ioch->read_error = 0;
- ioch->write_error = 0;
- #ifdef DEBUG
- ecrit_rapport("alloc_io_channel end\n");
- #endif
- return ioch;
- }
-
- static errcode_t my_open(const char *dev, int flags, io_channel *channel)
- {
- *channel = (io_channel*)dev;
- #ifdef DEBUG
- ecrit_rapport("my_open done\n");
- #endif
- return 0;
- }
-
- static errcode_t my_close(io_channel channel)
- {
- FREE(channel->private_data);
- FREE(channel->name);
- FREE(channel);
- #ifdef DEBUG
- ecrit_rapport("my_close done\n");
- #endif
- return 0;
- }
-
- static errcode_t my_set_blksize(io_channel channel, int blksize)
- {
- channel->block_size = blksize;
- #ifdef DEBUG
- ecrit_rapport("my_set_blksize done\n");
- #endif
- return 0;
- }
-
- static errcode_t my_read_blk(io_channel channel, unsigned long block, int count, void *buf)
- {
- size_t size;
- t_my_data *my_data=(t_my_data*)channel->private_data;
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
-
- size = (count < 0) ? -count : count * channel->block_size;
- #ifdef DEBUG
- ecrit_rapport("my_read_blk start\n");
- ecrit_rapport("size=%u, block=%u name=%s\n",size,block,my_data->partition->name);
- #endif
- if(my_data->disk_car->read(my_data->disk_car,size/512,buf,my_data->partition->lba+(block*channel->block_size/512))!=0)
- return 1;
- #ifdef DEBUG
- ecrit_rapport("my_read_blk done\n");
- #endif
- return 0;
- }
-
- static errcode_t my_write_blk(io_channel channel, unsigned long block, int count, const void *buf)
- {
- t_my_data *my_data=(t_my_data*)channel;
- EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
- /* if(my_data->disk_car->write(my_data->disk_car,count*channel->block_size/512,buf,my_data->partition->lba+(block*channel->block_size/512))!=0) */
- return 1;
- /* return 0; */
- }
-
- static errcode_t my_flush(io_channel channel)
- {
- return 0;
- }
-
- static int list_dir_proc(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private)
- {
- struct ext2_inode inode;
- ext2_ino_t ino;
- unsigned int thislen;
- struct list_dir_struct *ls = (struct list_dir_struct *) private;
- t_file_data *new_file=MALLOC(sizeof(*new_file));
- new_file->prev=ls->current_file;
- new_file->next=NULL;
-
- thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ?
- (dirent->name_len & 0xFF) : EXT2_NAME_LEN;
- if(thislen>DIR_NAME_LEN)
- thislen=DIR_NAME_LEN;
- memcpy(new_file->name, dirent->name, thislen);
- new_file->name[thislen] = '\0';
- ino = dirent->inode;
- if (ino) {
- if (ext2fs_read_inode(ls->current_fs,ino, &inode))
- {
- FREE(new_file);
- FREE(new_file);
- return 0;
- }
- } else {
- memset(&inode, 0, sizeof(struct ext2_inode));
- }
- new_file->filestat.st_dev=0;
- new_file->filestat.st_ino=ino;
- new_file->filestat.st_mode=inode.i_mode;
- new_file->filestat.st_nlink=inode.i_links_count;
- new_file->filestat.st_uid=inode.i_uid;
- new_file->filestat.st_gid=inode.i_gid;
- new_file->filestat.st_rdev=0;
- new_file->filestat.st_size=LINUX_S_ISDIR(inode.i_mode)?inode.i_size:
- inode.i_size| ((__u64)inode.i_size_high << 32);
- new_file->filestat.st_blksize=blocksize;
- #ifndef DJGPP
- new_file->filestat.st_blocks=inode.i_blocks;
- #endif
- new_file->filestat.st_atime=inode.i_atime;
- new_file->filestat.st_mtime=inode.i_mtime;
- new_file->filestat.st_ctime=inode.i_ctime;
- if(ls->current_file!=NULL)
- ls->current_file->next=new_file;
- else
- ls->dir_list=new_file;
- ls->current_file=new_file;
- return 0;
- }
-
- t_file_data *ext2_dir(t_param_disk *disk_car, const t_diskext *partition, t_dir_data *dir_data, const unsigned long int cluster);
- t_file_data *ext2_dir(t_param_disk *disk_car, const t_diskext *partition, t_dir_data *dir_data, const unsigned long int cluster)
- {
- struct list_dir_struct *ls=(struct list_dir_struct*)dir_data->private_dir_data;
- ls->dir_list=NULL;
- ls->current_file=NULL;
- ext2fs_dir_iterate(ls->current_fs, cluster, ls->flags, 0, list_dir_proc, ls);
- return ls->dir_list;
- }
-
- int dir_partition_ext2(WINDOW *window,t_param_disk *disk_car,t_diskext *partition, const int debug)
- {
- errcode_t retval;
- static struct list_dir_struct ls;
- io_channel ioch;
- ls.dir_list=NULL;
- ls.current_file=NULL;
- aff_buffer(BUFFER_RESET,"Q");
- wmove(window,4,0);
- aff_part(window,AFF_PART_NL,disk_car,partition);
- ecrit_rapport("\n");
- aff_part_rapport(disk_car,partition);
- ioch=alloc_io_channel(disk_car,partition);
- retval = ext2fs_open (ioch, 0, partition->boot_sector, partition->blocksize, my_io_manager, &ls.current_fs);
- if(retval)
- {
- aff_buffer(BUFFER_ADD,"Can't open ext2fs (retval=%u)\n",retval);
- aff_buffer(BUFFER_DISPLAY,"Q",window);
- return -1;
- }
- ls.flags = 0; /*DIRENT_FLAG_INCLUDE_EMPTY; */
- {
- t_dir_data dir_data;
- dir_data.window=window;
- dir_data.debug=debug;
- dir_data.private_dir_data=&ls;
- dir_data.get_dir=ext2_dir;
- strncpy(dir_data.current_directory,"/",sizeof(dir_data.current_directory));
- dir_partition(disk_car,partition,&dir_data,EXT2_ROOT_INO);
- }
- ext2fs_close (ls.current_fs);
- return 0;
- }
- #else
- #include "types.h"
- #include "common.h"
- #include "intrface.h"
-
- int dir_partition_ext2(WINDOW *window,t_param_disk *disk_car,t_diskext *partition)
- {
- aff_buffer(BUFFER_RESET,"Q");
- wmove(stdscr,5,0);
- aff_part(window,AFF_PART_NONL,disk_car,partition);
- aff_part_rapport(disk_car,partition);
- aff_buffer(BUFFER_ADD,"Recompile with e2fsprogs library");
- aff_buffer(BUFFER_DISPLAY,"Q",window);
- return 0;
- }
- #endif
-